Dynamic scripting languages are widely used in many industry and academic areas. For example, JavaScript is widely considered the dominant computer programming language for building client-side web applications; PHP typically is the backbone used to build server-side web applications; Python is widely used in building both high-level and low-level applications; Lua has been widely applied in the gaming industry and in embedded systems; R and Matlab have become popular for particular uses.
In general, the performance of dynamic scripting languages poses a concern. For example, applications written in dynamic scripting languages typically run slower and use more memory than applications based on static languages. Yet, in many scenarios memory usage is of critical importance. In typical embedded systems, for example, if an application requires more memory than is available the application will crash.
The memory used by an application generally includes a code section and a data section. In many applications, the code section can use up to half of the total required memory. As a result, reducing the amount of memory required for the code section can be an effective way to reduce overall application memory usage.
Existing solutions to reduce the amount of memory required for the code section include rewriting or restructuring the application to remove unnecessary code. This is made possible because applications typically include source code for all possible features of the application, even though some of the features generally will not be executed. Rewriting or restructuring the code can ensure only necessary code is included in the application.
However, rewriting or restructuring the code is relatively labor intensive, and thus, relatively expensive. Moreover, the decision regarding the usefulness or necessity of a section of code can be ambiguous based purely on static information. A more certain determination often is only possible using the information available at runtime.
Another reason dynamic scripting languages use more memory space is that by default dynamic scripting languages typically store all of the relevant debugging information for an application in the compiled object code, or bytecode, in memory. In some cases, the debug information occupies more than a third of the memory space used by the programming code. Nevertheless, the debug information typically is used only rarely, for example, when an error occurs during application execution or when reflection functions are invoked during execution.
Existing solutions to reduce the amount of memory required for the code section also include removing debug information by precompiling the application source code into bytecode. For example, Lua source code can be precompiled using the “-s” command extension to strip all debugging information in the source code, although an equivalent approach is not available in some dynamic scripting languages. However, use of such an approach does not permit retrieval of the debug information at runtime. In addition, when a runtime error occurs, the application is not able to report useful information, such as the line number in the code where the error occurred, variable names associated with the error, and the like.
In some cases, stripping the debug information from the code is not an acceptable solution, because certain application features required at runtime are dependent on the availability of the debugging information. Furthermore, removing the debugging information increases the deployment complexity, because the additional precompile step with the “-s” option is required to reach an intermediate stage (that is, bytecode) before the application is loaded into memory, whereas in general the dynamic scripting language source script has been directly executed.
Additionally, dynamic scripting language codes often are compressed using common data compression algorithms. Even though the uncompressed version of precompiled bytecode may occupy less memory than the uncompressed source code, after compression the precompiled code can occupy more memory space than the original text-format source code. Thus, in some applications—for example, in embedded systems with limited flash memory—it is desirable to store source code, rather than precompiled bytecode, to further reduce the amount of required memory.